"""
法币汇率模块
获取法币汇率数据（2周平均汇率）
"""
import time
from typing import Dict, List, Optional
from datetime import datetime, timedelta
from loguru import logger

try:
    import okx.MarketData as MarketData
except ImportError:
    logger.warning("okx SDK未安装，请运行: pip install okx")
    MarketData = None


class ExchangeRateManager:
    """法币汇率管理器"""
    
    # 限速配置：1次/2s
    RATE_LIMIT_REQUESTS = 1
    RATE_LIMIT_WINDOW = 2.0  # 秒
    
    def __init__(self, sandbox: bool = True):
        """
        初始化法币汇率管理器
        
        Args:
            sandbox: 是否使用模拟盘，True=模拟盘(1)，False=实盘(0)
        """
        if MarketData is None:
            raise ImportError("okx SDK未安装，请运行: pip install okx")
        
        self.sandbox = sandbox
        flag = "1" if sandbox else "0"
        
        # 初始化OKX行情数据API
        self.market_api = MarketData.MarketAPI(flag=flag)
        
        # 限速控制
        self.request_times: List[float] = []  # 请求时间戳列表
        
        # 数据缓存（汇率数据是2周平均值，变化不频繁，可以缓存较长时间）
        self.rate_cache: Optional[Dict] = None
        self.cache_expire_time: Optional[datetime] = None
        self.cache_duration = timedelta(hours=1)  # 缓存1小时
        
        logger.info(f"法币汇率管理器已初始化 (模式: {'模拟盘' if sandbox else '实盘'})")
    
    def _check_rate_limit(self):
        """
        检查并执行限速
        限速规则：1次/2s (IP)
        """
        now = time.time()
        
        # 移除2秒前的请求记录
        self.request_times = [t for t in self.request_times 
                             if now - t < self.RATE_LIMIT_WINDOW]
        
        # 如果达到限速上限，等待
        if len(self.request_times) >= self.RATE_LIMIT_REQUESTS:
            oldest_request = self.request_times[0]
            wait_time = self.RATE_LIMIT_WINDOW - (now - oldest_request)
            
            if wait_time > 0:
                logger.debug(f"触发限速，等待 {wait_time:.2f} 秒")
                time.sleep(wait_time)
                # 重新计算
                now = time.time()
                self.request_times = [t for t in self.request_times 
                                     if now - t < self.RATE_LIMIT_WINDOW]
        
        # 记录本次请求
        self.request_times.append(now)
    
    def get_exchange_rate(self, use_cache: bool = True) -> Dict:
        """
        获取法币汇率
        该接口提供的是2周的平均汇率数据
        
        Args:
            use_cache: 是否使用缓存
            
        Returns:
            汇率数据字典，包含：
            - usdCny: 美元兑人民币汇率
            - 其他法币汇率数据
        """
        # 检查缓存
        if use_cache and self.rate_cache is not None:
            if self.cache_expire_time and datetime.now() < self.cache_expire_time:
                logger.debug("从缓存获取法币汇率")
                return self.rate_cache
        
        # 执行限速检查
        self._check_rate_limit()
        
        try:
            logger.info("获取法币汇率（2周平均值）")
            result = self.market_api.get_exchange_rate()
            
            # 检查响应
            if result.get("code") != "0":
                error_msg = result.get("msg", "未知错误")
                logger.error(f"获取法币汇率失败: {error_msg}")
                raise RuntimeError(f"API错误: {error_msg}")
            
            # 提取数据
            data = result.get("data", [])
            if not data:
                logger.warning("未获取到法币汇率数据")
                return {}
            
            # 通常返回一个对象
            rate_data = data[0] if isinstance(data, list) else data
            
            logger.info(f"获取法币汇率成功")
            
            # 更新缓存
            if use_cache:
                self.rate_cache = rate_data
                self.cache_expire_time = datetime.now() + self.cache_duration
            
            return rate_data
            
        except Exception as e:
            logger.error(f"获取法币汇率异常: {e}")
            raise
    
    def get_usd_cny_rate(self, use_cache: bool = True) -> Optional[float]:
        """
        获取美元兑人民币汇率
        
        Args:
            use_cache: 是否使用缓存
            
        Returns:
            美元兑人民币汇率，如果不存在返回None
        """
        rate_data = self.get_exchange_rate(use_cache)
        
        if rate_data and "usdCny" in rate_data:
            return float(rate_data["usdCny"])
        
        return None
    
    def convert_usd_to_cny(self, usd_amount: float, use_cache: bool = True) -> Optional[float]:
        """
        将美元金额转换为人民币
        
        Args:
            usd_amount: 美元金额
            use_cache: 是否使用缓存
            
        Returns:
            人民币金额，如果汇率不存在返回None
        """
        rate = self.get_usd_cny_rate(use_cache)
        
        if rate is not None:
            cny_amount = usd_amount * rate
            logger.debug(f"转换: ${usd_amount:.2f} USD = ¥{cny_amount:.2f} CNY (汇率: {rate})")
            return cny_amount
        
        return None
    
    def convert_cny_to_usd(self, cny_amount: float, use_cache: bool = True) -> Optional[float]:
        """
        将人民币金额转换为美元
        
        Args:
            cny_amount: 人民币金额
            use_cache: 是否使用缓存
            
        Returns:
            美元金额，如果汇率不存在返回None
        """
        rate = self.get_usd_cny_rate(use_cache)
        
        if rate is not None and rate > 0:
            usd_amount = cny_amount / rate
            logger.debug(f"转换: ¥{cny_amount:.2f} CNY = ${usd_amount:.2f} USD (汇率: {rate})")
            return usd_amount
        
        return None
    
    def get_rate_details(self, use_cache: bool = True) -> Dict:
        """
        获取汇率详细信息
        
        Args:
            use_cache: 是否使用缓存
            
        Returns:
            详细信息字典
        """
        rate_data = self.get_exchange_rate(use_cache)
        
        if not rate_data:
            return {}
        
        usd_cny = float(rate_data.get("usdCny", 0))
        
        details = {
            "usd_cny_rate": usd_cny,
            "data_period": "2周平均值",
            "update_time": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        }
        
        # 添加其他可能的汇率字段
        for key, value in rate_data.items():
            if key != "usdCny":
                details[key] = value
        
        return details
    
    def clear_cache(self):
        """清除缓存"""
        self.rate_cache = None
        self.cache_expire_time = None
        logger.info("已清除法币汇率缓存")
    
    def get_cache_stats(self) -> Dict:
        """
        获取缓存统计信息
        
        Returns:
            缓存统计字典
        """
        is_cached = self.rate_cache is not None
        is_valid = False
        
        if is_cached and self.cache_expire_time:
            is_valid = datetime.now() < self.cache_expire_time
        
        return {
            "is_cached": is_cached,
            "is_valid": is_valid,
            "cache_duration_seconds": self.cache_duration.total_seconds(),
        }


# 便捷函数
def get_exchange_rate(sandbox: bool = True) -> Dict:
    """
    便捷函数：获取法币汇率
    
    Args:
        sandbox: 是否使用模拟盘
        
    Returns:
        汇率数据字典
    """
    manager = ExchangeRateManager(sandbox=sandbox)
    return manager.get_exchange_rate()


def get_usd_cny_rate(sandbox: bool = True) -> Optional[float]:
    """
    便捷函数：获取美元兑人民币汇率
    
    Args:
        sandbox: 是否使用模拟盘
        
    Returns:
        美元兑人民币汇率
    """
    manager = ExchangeRateManager(sandbox=sandbox)
    return manager.get_usd_cny_rate()


def convert_usd_to_cny(usd_amount: float, sandbox: bool = True) -> Optional[float]:
    """
    便捷函数：将美元转换为人民币
    
    Args:
        usd_amount: 美元金额
        sandbox: 是否使用模拟盘
        
    Returns:
        人民币金额
    """
    manager = ExchangeRateManager(sandbox=sandbox)
    return manager.convert_usd_to_cny(usd_amount)


def convert_cny_to_usd(cny_amount: float, sandbox: bool = True) -> Optional[float]:
    """
    便捷函数：将人民币转换为美元
    
    Args:
        cny_amount: 人民币金额
        sandbox: 是否使用模拟盘
        
    Returns:
        美元金额
    """
    manager = ExchangeRateManager(sandbox=sandbox)
    return manager.convert_cny_to_usd(cny_amount)
